package com.wuuxiang.polestar.admin.dao;

import com.google.common.base.Charsets;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.wuuxiang.polestar.admin.dto.PropertyItem;
import org.apache.curator.framework.api.GetChildrenBuilder;
import org.apache.curator.framework.api.GetDataBuilder;
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 项目名称：polestar        <br>
 * 类描述：                         <br>
 * 创建人：夏鸿鹏                    <br>
 * 创建时间：2017-11-28 10:51        <br>
 * 修改备注：                        <br>
 */

@Component
public class PropertyDao extends BaseDao implements IPropertyDao {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LoggerFactory.getLogger(PropertyDao.class);

    @Override
    public boolean createProperty(String nodeName, String value) {
        LOGGER.debug("Create property : [{}] = [{}]", nodeName, value);
        boolean suc = false;
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat == null) {
                final byte[] data = Strings.isNullOrEmpty(value) ? new byte[]{} : value.getBytes(Charsets.UTF_8);
                String opResult = getClient().create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(nodeName, data);
                suc = Objects.equal(nodeName, opResult);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return suc;
    }

    @Override
    public boolean createTempProperty(String nodeName, String value) {
        LOGGER.debug("Create tempproperty : [{}] = [{}]", nodeName, value);
        boolean suc = false;
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat == null) {
                final byte[] data = Strings.isNullOrEmpty(value) ? new byte[]{} : value.getBytes(Charsets.UTF_8);
                String opResult = getClient().create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(nodeName, data);
                suc = Objects.equal(nodeName, opResult);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return suc;
    }

    @Override
    public boolean checkExists(String nodeName) {
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat == null) {
                return false;
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public boolean updateProperty(String nodeName, String value) {
        LOGGER.debug("Update property: [{}] = [{}]", nodeName, value);
        boolean suc = false;
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat != null) {
                Stat opResult = getClient().setData().forPath(nodeName, value.getBytes(Charsets.UTF_8));
                suc = opResult != null;
            } else {
                String opResult = getClient().create().creatingParentsIfNeeded().forPath(nodeName, value.getBytes(Charsets.UTF_8));
                suc = Objects.equal(nodeName, opResult);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return suc;
    }

    @Override
    public void deleteProperty(String nodeName) {
        LOGGER.debug("Delete property: [{}]", nodeName);
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat != null) {
                getClient().delete().deletingChildrenIfNeeded().forPath(nodeName);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
    }

    @Override
    public List<String> listChildren(String nodeName) {
        LOGGER.debug("Find children of node: [{}]", nodeName);
        List<String> children = null;
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat != null) {
                GetChildrenBuilder childrenBuilder = getClient().getChildren();
                children = childrenBuilder.forPath(nodeName);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return children;
    }
    
    
    @Override
    public String getProperty(String nodeName) {
        LOGGER.debug("Find children of node: [{}]", nodeName);
        String data = null;
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat != null) {
            	byte[] dataByte = getClient().getData().forPath(nodeName);
            	data = new String(dataByte, Charsets.UTF_8);
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return data;
    }
    

    @Override
    public List<PropertyItem> findProperties(String nodeName) {
        LOGGER.debug("Find properties in node: [{}]", nodeName);
        List<PropertyItem> properties = Lists.newArrayList();
        try {
            Stat stat = getClient().checkExists().forPath(nodeName);
            if (stat != null) {
                GetChildrenBuilder childrenBuilder = getClient().getChildren();
                List<String> children = childrenBuilder.forPath(nodeName);
                GetDataBuilder dataBuilder = getClient().getData();
                if (children != null) {
                    for (String child : children) {
                        String propPath = ZKPaths.makePath(nodeName, child);
                        PropertyItem item = new PropertyItem(child, new String(dataBuilder.forPath(propPath), Charsets.UTF_8));
                        properties.add(item);
                    }
                }
            }
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
        return properties;
    }
}
